/* 
 * File:   UnaryOperator.cpp
 * Author: Gab'z
 * 
 * Created on 29 mai 2012, 22:03
 */

#include "UnaryOperator.h"
#include "../model/memento/StackMemento.h"
#include "../model/Context.h"
#include "../../literal/Constant.h"
#include "../../literal/Expression.h"
#include "../../literal/Complex.h"

namespace calculator {

    UnaryOperator::UnaryOperator(const std::string name) : Operator(name) {
    }

    UnaryOperator::UnaryOperator(const UnaryOperator& orig) :
    Operator(orig._name) {
    }

    UnaryOperator::~UnaryOperator() {
    }

    std::string UnaryOperator::isExecutable() const {
        if (Context::getInstance()->getCurrentStack()->size() == 0) return "Empty stack";
        if (dynamic_cast<const Complex*> (Context::getInstance()->getCurrentStack()->getConstant(0)) != 0) return "Cannot convert complex to simple number";
        return "";
    }

    const Memento* UnaryOperator::createMemento() const throw (CommandException) {
        Stack* stack = new Stack();
        if (Context::getInstance()->getCurrentStack()->size() == 0) throw CommandException("Not enough Constant in current stack (0/1)");
        stack->push(Context::getInstance()->getCurrentStack()->top());
        return new StackMemento(clone(), stack);
    }

    void UnaryOperator::eval(Stack* stack) const throw (CommandException) {
        if (stack->size() == 0) throw CommandException("Not enough Constant in current stack (0/1)");
        const Constant* c = stack->getConstant(0);
        const Expression* exp = dynamic_cast<const Expression*> (c);
        const Constant* constant;
        if (exp != 0) {
            constant = new Expression(c, this);
        } else {
            const Number* n = dynamic_cast<const Number*> (c);
            try {
                constant = apply(n);
            } catch (ArithmeticException& e) {
                throw;
            }
        }
        stack->pop();
        stack->push(constant);
        delete constant;
    }
}
